﻿using System;
using System.Security.Principal;
using System.Web;
using System.Web.Mvc;
using System.Web.Security;
using UIShell.OSGi;
using UIShell.OSGI.Mvc;

namespace Isaac.Joy.Identity.Module
{
    public class PermissionAttribute : AuthorizeAttribute
    {
        public const string FormsCookieName = "Admin.AUTH";
        private readonly string _roleCode;
        private readonly bool _all;

        private bool _isNoPermission;

        private static string _noPermissionUrl;
        protected string NoPermissionUrl
        {
            get
            {
                if (_noPermissionUrl == "/") return null;
                if (string.IsNullOrEmpty(_noPermissionUrl))
                {
                    var extensions = Activator.BundleContext.GetExtensions("Isaac.Joy.Identity.NoPermissionUrl");
                    if (extensions.Count <= 0)
                    {
                        _noPermissionUrl = "/";
                        return _noPermissionUrl;
                    }
                    if (extensions[0].Data.Count <= 0)
                    {
                        _noPermissionUrl = "/";
                        return _noPermissionUrl;
                    }

                    var xmlAttributeCollection = extensions[0].Data[0].Attributes;
                    if (xmlAttributeCollection == null || xmlAttributeCollection["value"] == null)
                    {
                        _noPermissionUrl = "/";
                        return _noPermissionUrl;
                    }
                    _noPermissionUrl = xmlAttributeCollection["value"].Value;
                }
                return _noPermissionUrl;
            }
        }

        public PermissionAttribute()
        {
            _all = true;
        }

        public PermissionAttribute(string roleCode)
        {
            _roleCode = roleCode;
        }

        protected override bool AuthorizeCore(HttpContextBase httpContext)
        {
            var symbolicName = httpContext.Request.RequestContext.RouteData.GetPluginSymbolicName();
            if (string.IsNullOrEmpty(symbolicName)) return false;

            //读取cookie
            var cookie = httpContext.Request.Cookies[FormsCookieName];
            if (cookie == null) return false;

            //转换为票据
            FormsAuthenticationTicket ticket;
            try
            {
                ticket = FormsAuthentication.Decrypt(cookie.Value);
            }
            catch (Exception)
            {
                return false;
            }
            if (ticket == null) return false;

            if (!_all)
            {
                //读取票据信息
                var rolestr = ticket.UserData;

                var repository = BundleRuntime.Instance.GetFirstOrDefaultService<IRepository>();
                var permission = repository.GetPermission(_roleCode, symbolicName);

                if (permission== null || !new FlagsValue(rolestr).Enabled(permission.Id))
                {
                    _isNoPermission = true;
                    return false;
                }
            }

            var ideitity = new FormsIdentity(ticket);
            var principal = new GenericPrincipal(ideitity, null);
            httpContext.User = principal;

            return true;
        }

        public override void OnAuthorization(AuthorizationContext filterContext)
        {
            base.OnAuthorization(filterContext);

            if (_isNoPermission && !string.IsNullOrEmpty(NoPermissionUrl))
            {
                var identity = filterContext.RequestContext.HttpContext.User.Identity as FormsIdentity;
                if (identity == null || !identity.IsAuthenticated)
                {
                    filterContext.Result = new RedirectResult(NoPermissionUrl);
                }
            }
        }
    }
}
